package com.csair.seam.infrastructure.poi.service.impl;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.csair.seam.infrastructure.poi.config.ExcelExportConfig;
import com.csair.seam.infrastructure.poi.entity.ExportFieldEntity;
import com.csair.seam.infrastructure.poi.entity.ImportFieldEntity;
import com.csair.seam.infrastructure.poi.exception.ExcelException;
import com.csair.seam.infrastructure.poi.factory.ExcelMappingFactory;
import com.csair.seam.infrastructure.poi.service.ExportExcelService;

public class ExportExcelServiceImpl implements ExportExcelService {
	private Workbook workbook;
	private ExcelExportConfig config;
	private CellStyle headerCellStyle;
	public ExportExcelServiceImpl(ExcelExportConfig config,boolean xssf) throws IOException {
		this.config = config;
		this.workbook = WorkbookFactory.create(xssf);
		setHeaderCellStyle();
	}
	
	@Override
	public <T> void exportExcel(List<T> dataList, Object queryParams, OutputStream out) {
		if(CollectionUtils.isEmpty(dataList)) {
			throw new ExcelException("导出数据集合为空");
		}
		try {
			int totalRecord = dataList.size();
			
			if(totalRecord > 10000) {
				this.workbook = new SXSSFWorkbook(1000);
			}
			
			int pageSize = config.getPerPageSize();
			int pageSheet = (totalRecord  +  pageSize  - 1) / pageSize;
			for(int i=0;i<pageSheet;i++) {
				int beginIndex = i*pageSize;
				int endIndex = (i+1)*pageSize;
				if(endIndex > totalRecord) {
					endIndex = totalRecord;
				}
				writeData(dataList,queryParams,beginIndex,endIndex);
			}
			workbook.write(out);
		} catch (IOException e) {
			throw new ExcelException(e);
		}finally {
			IOUtils.closeQuietly(workbook);
		}
	}
	
	
	@Override
	public void exportTemplate(Class<?> pojoClass, OutputStream out) {
		Map<String, ImportFieldEntity> fieldMap = ExcelMappingFactory.loadImportFieldClass(pojoClass);
		Sheet sheet = workbook.createSheet();
		sheet.setDefaultColumnWidth(15);
		Row rowTitle = sheet.createRow(0);
        rowTitle.setHeightInPoints(24);
		int columnIndex = 0;
		for (String header : fieldMap.keySet()) {
			Cell cell = rowTitle.createCell(columnIndex);
        	cell.setCellStyle(headerCellStyle);
        	cell.setCellValue(header);
        	columnIndex++;
		}
		try {
			workbook.write(out);
		} catch (IOException e) {
			throw new ExcelException(e);
		}finally {
			IOUtils.closeQuietly(workbook);
		}
	}
	
	private <T> void writeData(List<T> dataList, Object queryParams,int beginIndex,int endIndex) {
		Map<String, ExportFieldEntity> exportHeaderMap = ExcelMappingFactory.loadExportFieldClass(dataList.get(0).getClass(), config);
		Sheet sheet = workbook.createSheet();
		sheet.setDefaultColumnWidth(15);
		int currentRowIndex = 0 ;
		if(queryParams != null) {
			CellRangeAddress region = new CellRangeAddress(0, 0, 0, exportHeaderMap.size()-1);
			sheet.addMergedRegion(region);
			Row paramsRow = sheet.createRow(currentRowIndex);
			paramsRow.setHeightInPoints(24);
			Cell cell = paramsRow.createCell(0);
			cell.setCellValue(JSON.toJSONString(queryParams));
			cell.setCellStyle(headerCellStyle);
			currentRowIndex ++;
		}
		setHeaderRow(sheet.createRow(currentRowIndex),exportHeaderMap);
		currentRowIndex ++;
		for(int i=beginIndex;i<endIndex;i++) {
			T t = dataList.get(i);
			Row dataRow = sheet.createRow(currentRowIndex);
			JSONObject objectJSON = JSON.parseObject(JSON.toJSONString(t));
			int cellIndex = 0;
			for (Entry<String, ExportFieldEntity> entry : exportHeaderMap.entrySet()) {
				Cell cell = dataRow.createCell(cellIndex);
				ExportFieldEntity entity = entry.getValue();
				setCellValue(cell, objectJSON, entity);
				cellIndex++;
			}
			currentRowIndex ++;
		}
	}
	
	private void setHeaderRow(Row headerRow,Map<String, ExportFieldEntity> exportHeaderMap) {
		int cellIndex = 0;
		headerRow.setHeightInPoints(24);
		for (Entry<String, ExportFieldEntity> entry : exportHeaderMap.entrySet()) {
			Cell cell = headerRow.createCell(cellIndex);
			cell.setCellValue(entry.getValue().getExportField().columnName());
			cell.setCellStyle(headerCellStyle);
			cellIndex++;
		}
	}
	
	private void setCellValue(Cell cell,JSONObject objectJSON,ExportFieldEntity entity) {
		Object valueObj = objectJSON.get(entity.getFieldName());
		if(null == valueObj) {
			return;
		}
		String value = String.valueOf(valueObj);
		if(StringUtils.isBlank(value)) {
			return;
		}
		if("Date".equals(entity.getSimpleJavaType())) {
			Date date = objectJSON.getDate(entity.getFieldName());
			cell.setCellValue(DateFormatUtils.format(date, entity.getExportField().dateFormat()));
		}else if("Long".equals(entity.getSimpleJavaType()) || "long".equals(entity.getSimpleJavaType())){
			cell.setCellValue(Long.parseLong(value));
		}else if("Integer".equals(entity.getSimpleJavaType()) || "int".equals(entity.getSimpleJavaType())){
			cell.setCellValue(Integer.parseInt(value));
		}else {
			cell.setCellValue(value);
		}
	}
	
	private void setHeaderCellStyle() {
		headerCellStyle = workbook.createCellStyle();
		headerCellStyle.setAlignment(HorizontalAlignment.CENTER);//居中
		headerCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直
		headerCellStyle.setBorderBottom(BorderStyle.THIN); //下边框
		headerCellStyle.setBorderLeft(BorderStyle.THIN);//左边框
		headerCellStyle.setBorderTop(BorderStyle.THIN);//上边框
		headerCellStyle.setBorderRight(BorderStyle.THIN);//右边框
		
		Font fontTitle = workbook.createFont();
        fontTitle.setFontName("宋体");
        fontTitle.setBold(true);
        fontTitle.setFontHeightInPoints((short) 12);
        headerCellStyle.setFont(fontTitle);
	}

}
